//-*****************************************************************************
//
// Copyright (c) 2013,
//  Sony Pictures Imageworks Inc. and
//  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// *       Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// *       Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// *       Neither the name of Sony Pictures Imageworks, nor
// Industrial Light & Magic, nor the names of their contributors may be used
// to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//-*****************************************************************************

#ifndef MARI_ALEMBIC_READER_H
#define MARI_ALEMBIC_READER_H

#include <hdf5.h>
#include <ImathMath.h>
#include <ImathVec.h>
#include <Alembic/AbcCoreHDF5/All.h>
#include <Alembic/AbcGeom/All.h>

#include <sstream>
#include <set>

#include "MriAlembicIn.h"
#include "TreeEntry.h"
#include "OptionsData.h"

#include "MriGeoReaderPlugin.h"

using namespace Alembic;
using namespace Alembic::Abc;
using namespace std;


namespace mariAlembic
{

class OptionsData;
class TreeEntry;

#define ITEM_UNKNOWN    0
#define ITEM_TRANSFORM  1
#define ITEM_POLYMESH   2
#define ITEM_SUBD       3
#define ITEM_CAMERA     4
#define ITEM_CURVES     5
#define ITEM_NURBSPATCH 6
#define ITEM_POINTS     7


#define RTOD (180.0/3.14159265359)
#define DTOR (3.14159265359/180.0)


#define CHECK_RESULT(expr)  { \
                                Result = expr; \
                                if (Result != MRI_GPR_SUCCEEDED) \
                                    return Result; \
                            }


class AlembicReader
{

public:

    AlembicReader(OptionsData *wd, const char *file, MriGeoReaderHostV1 *shost)
    {
        widgetData = wd;
        pFileName = file;
        s_Host = shost;
        materialAttrName = "material"; // default material attribute name.
    };

    ~AlembicReader()
    {
        freeArchive();
    };

    bool loadArchive(const std::string & path);
    void freeArchive(void);

    int getType(Alembic::Abc::IObject & iObj);
    int processObject(IObject iObj, M44d matrix, MriGeoEntityHandle Entity,
        TreeEntry &tree);
    bool processObjectData(MriGeoEntityHandle Entity);
    bool loadAlembic(MriGeoEntityHandle Entity);

    bool queryAlembicData(vector<string> &shapeNames);
    int retrieveObjectData(IObject iObj, vector<string> &shapeNames,
                           TreeEntry &tree);

    string getShortName(string &path);

    M44d processTransform(IObject &iObj);
    bool processMesh(IObject &iObj, M44d matrix,  MriGeoEntityHandle Entity,
        string &path);

    void processArbitraryGeomParams(Abc::ICompoundProperty & parent,
        AbcGeom::IPolyMesh &meshObject, string &path);

    void getNormals(AbcGeom::IPolyMesh &meshObject,
        Alembic::Abc::N3fArraySamplePtr &normalVal, size_t *normalSize,
        string &path);

    void getUVs(AbcGeom::IPolyMesh &meshObject,
        AbcGeom::IV2fGeomParam &uvParam,
        Alembic::AbcGeom::V2fArraySamplePtr &uvPtr,
        Alembic::Abc::UInt32ArraySamplePtr &uvIndexPtr, string &path);

    bool createMesh(int triVertCnt, vector<float>&tris, vector<int>&indices,
        vector<float>&normals, vector<float>&uvs, MriGeoEntityHandle Entity,
        string &path);


    void getArbStringParam(Abc::ICompoundProperty & parent,
        const std::string &propName, Abc::chrono_t sampleTime, string &val);

    void getArbBoolParam(Abc::ICompoundProperty & parent,
        const std::string &propName, Abc::chrono_t sampleTime, bool &val);

    void getArbIntParam(Abc::ICompoundProperty & parent,
        const std::string &propName, Abc::chrono_t sampleTime, int &val);

    // pointer to the global instance of the dialog data
    OptionsData *widgetData;

    // path of the alembic file
    string pFileName;

    MriGeoReaderHostV1 *s_Host;

    // abc archive
    IArchive archive;

    // root entry
    IObject root;

    // name of the material attribute
    string materialAttrName;

private:



};


}


#endif
